home *** CD-ROM | disk | FTP | other *** search
/ HAM Radio 3.2 / Ham Radio Version 3.2 (Chestnut CD-ROMs)(1993).ISO / packet / n17jsrc / pppfsm.c < prev    next >
C/C++ Source or Header  |  1991-06-07  |  18KB  |  848 lines

  1. /*
  2.  *  PPPFSM.C    -- PPP Finite State Machine
  3.  *
  4.  *    This implementation of PPP is declared to be in the public domain.
  5.  *
  6.  *    Jan 91    Bill_Simpson@um.cc.umich.edu
  7.  *        Computer Systems Consulting Services
  8.  *
  9.  *    Acknowledgements and correction history may be found in PPP.C
  10.  */
  11.  
  12. #include <stdio.h>
  13. #include <ctype.h>
  14. #include <time.h>
  15. #include "global.h"
  16. #include "mbuf.h"
  17. #include "iface.h"
  18. #include "ppp.h"
  19. #include "pppfsm.h"
  20. #include "ppplcp.h"
  21.  
  22.  
  23. char *fsmStates[] = {
  24.     "Closed",
  25.     "Listen",
  26.     "Req Sent",
  27.     "Ack Rcvd",
  28.     "Ack Sent",
  29.     "Open",
  30.     "TermSent"
  31. };
  32.  
  33. char *fsmCodes[] = {
  34.     NULLCHAR,
  35.     "Configure Request",
  36.     "Configure Ack",
  37.     "Configure Nak",
  38.     "Configure Reject",
  39.     "Terminate Request",
  40.     "Terminate Ack",
  41.     "Code Reject",
  42.     "Protocol Reject",
  43.     "Echo Request",
  44.     "Echo Reply",
  45.     "Discard Request",
  46. };
  47.  
  48. static int fsm_sendtermreq __ARGS((struct fsm_s *fsm_p));
  49. static int fsm_sendtermack __ARGS((struct fsm_s *fsm_p, byte_t id));
  50.  
  51. static void fsm_timeout __ARGS((void *vp));
  52.  
  53. static void fsm_reset __ARGS((struct fsm_s *fsm_p));
  54. static void fsm_opening __ARGS((struct fsm_s *fsm_p));
  55.  
  56.  
  57. /************************************************************************/
  58. /* Convert header in host form to network form */
  59. struct mbuf *
  60. htoncnf(cnf, data)
  61. struct config_hdr *cnf;
  62. struct mbuf *data;
  63. {
  64.     struct mbuf *bp;
  65.     register char *cp;
  66.  
  67.     /* Prepend bytes for LCP/IPCP header */
  68.     if ((bp = pushdown(data, CONFIG_HDR_LEN)) == NULLBUF)
  69.         return NULLBUF;
  70.  
  71.     /* Load header with proper values */
  72.     cp = bp->data;
  73.     *cp++ = cnf->code;
  74.     *cp++ = cnf->id;
  75.     put16(cp, cnf->len);
  76.  
  77.     return bp;
  78. }
  79.  
  80. /* Extract header from incoming packet */
  81. int
  82. ntohcnf(cnf, bpp)
  83. struct config_hdr *cnf;
  84. struct mbuf **bpp;
  85. {
  86.     if (cnf== NULL || bpp == NULLBUFP
  87.      || *bpp == NULLBUF)
  88.         return -1;
  89.  
  90.     cnf->code = pullchar(bpp);
  91.     cnf->id = pullchar(bpp);
  92.     cnf->len = pull16(bpp);
  93.     return 0;
  94. }
  95.  
  96. /***************************************/
  97. /* Convert configuration option header in host form to network form */
  98. struct mbuf *
  99. htonopt(opt)
  100. struct option_hdr *opt;
  101. {
  102.     struct mbuf *bp;
  103.     register char *cp;
  104.  
  105.     if((bp = alloc_mbuf(OPTION_HDR_LEN)) == NULLBUF)
  106.         return NULLBUF;
  107.  
  108.     /* Load data into LCP/IPCP configuration option header */
  109.     cp = bp->data;
  110.     *cp++ = opt->type;
  111.     *cp++ = opt->len;
  112.  
  113.     bp->cnt = cp - bp->data;
  114.     return bp;
  115. }
  116.  
  117. /* Extract configuration option header */
  118. int
  119. ntohopt(opt,bpp)
  120. struct option_hdr *opt;
  121. struct mbuf **bpp;
  122. {
  123.     if (opt== NULLOPTHDR || bpp == NULLBUFP
  124.      || *bpp == NULLBUF)
  125.         return -1;
  126.  
  127.     opt->type = pullchar(bpp);
  128.     opt->len = pullchar(bpp);
  129.     return 0;
  130. }
  131.  
  132.  
  133. /************************************************************************/
  134. void
  135. fsm_no_action(fsm_p)
  136. struct fsm_s *fsm_p;
  137. {
  138.     PPP_DEBUG_ROUTINES("fsm_no_action()");
  139. }
  140. int
  141. fsm_no_check(fsm_p, hdr, bp)
  142. struct fsm_s *fsm_p;
  143. struct config_hdr *hdr;
  144. struct mbuf *bp;
  145. {
  146.     PPP_DEBUG_ROUTINES("fsm_no_check()");
  147.     return 0;
  148. }
  149.  
  150.  
  151. /************************************************************************/
  152. /* General log routine */
  153. void
  154. fsm_log(fsm_p, comment)
  155. struct fsm_s *fsm_p;
  156. char *comment;
  157. {
  158.     if (PPPtrace)
  159.         log(-1,"%s PPP/%s %-8s; %s",
  160.             fsm_p->ppp_p->iface->name,
  161.             fsm_p->pdc->name,
  162.             fsmStates[fsm_p->state],
  163.             comment);
  164. }
  165.  
  166.  
  167. /************************************************************************/
  168. /* Set a timer in case an expected event does not occur */
  169. void
  170. fsm_timer(fsm_p)
  171. struct fsm_s *fsm_p;
  172. {
  173.     PPP_DEBUG_ROUTINES("fsm_timer()");
  174.  
  175.     start_timer( &(fsm_p->timer) );
  176. }
  177.  
  178.  
  179. /************************************************************************/
  180. /* Send a packet to the remote host */
  181. int
  182. fsm_send(fsm_p,code,id,data)
  183. struct fsm_s *fsm_p;
  184. byte_t code;
  185. byte_t id;
  186. struct mbuf *data;
  187. {
  188.     struct ppp_s *ppp_p = fsm_p->ppp_p;
  189.     struct iface *iface = ppp_p->iface;
  190.     struct config_hdr hdr;
  191.  
  192.     switch( hdr.code = code ) {
  193.     case CONFIG_REQ:
  194.     case TERM_REQ:
  195.     case ECHO_REQ:
  196.         /* Save ID field for match against replies from remote host */
  197.         fsm_p->lastid = ppp_p->id;
  198.         /* fallthru */
  199.     case PROT_REJ:
  200.     case DISCARD_REQ:
  201.         /* Use a unique ID field value */
  202.         hdr.id = ppp_p->id++;
  203.         break;
  204.  
  205.     case CONFIG_ACK:
  206.     case CONFIG_NAK:
  207.     case CONFIG_REJ:
  208.     case TERM_ACK:
  209.     case CODE_REJ:
  210.     case ECHO_REPLY:
  211.         /* Use ID sent by remote host */
  212.         hdr.id = id;
  213.         break;
  214.  
  215.     default:
  216.         /* we're in trouble */
  217.         log(-1, "%s PPP/%s %-8s;"
  218.             " Send with bogus code: %d",
  219.             iface->name,
  220.             fsm_p->pdc->name,
  221.             fsmStates[fsm_p->state],
  222.             code);
  223.         return -1;
  224.     };
  225.  
  226.     switch( code ) {
  227.     case ECHO_REQ:
  228.     case ECHO_REPLY:
  229.     case DISCARD_REQ:
  230.     {
  231.         struct lcp_s *lcp_p = fsm_p->pdv;
  232.         data = pushdown(data, 4);
  233.         put32(data->data, lcp_p->local.work.magic_number);
  234.     }
  235.     };
  236.  
  237.     hdr.len = len_p(data) + CONFIG_HDR_LEN;
  238.  
  239.     /* Prepend header to packet data */
  240.     if ((data = htoncnf(&hdr,data)) == NULLBUF)
  241.         return -1;
  242.  
  243.     if (PPPtrace > 1) {
  244.         log(-1, "%s PPP/%s %-8s;"
  245.             " Sending option: %s, id: %d, len: %d",
  246.             iface->name,
  247.             fsm_p->pdc->name,
  248.             fsmStates[fsm_p->state],
  249.             fsmCodes[code],
  250.             hdr.id,hdr.len);
  251.     }
  252.  
  253.     ppp_p->OutNCP[fsm_p->pdc->fsmi]++;
  254.  
  255.     return( (*iface->output)
  256.         (iface, NULLCHAR, NULLCHAR, fsm_p->pdc->protocol, data) );
  257. }
  258.  
  259.  
  260. /************************************************************************/
  261. /* Send a configuration request */
  262. int
  263. fsm_sendreq(fsm_p)
  264. struct fsm_s *fsm_p;
  265. {
  266.     struct mbuf *bp;
  267.  
  268.     PPP_DEBUG_ROUTINES("fsm_sendreq()");
  269.  
  270.     if ( fsm_p->retry <= 0 )
  271.         return -1;
  272.  
  273.     fsm_p->retry--;
  274.     fsm_timer(fsm_p);
  275.  
  276.     bp = (*fsm_p->pdc->makereq)(fsm_p);
  277.     return( fsm_send(fsm_p, CONFIG_REQ, 0, bp) );
  278. }
  279.  
  280.  
  281. /************************************************************************/
  282. /* Send a termination request */
  283. static int
  284. fsm_sendtermreq(fsm_p)
  285. struct fsm_s *fsm_p;
  286. {
  287.     PPP_DEBUG_ROUTINES("fsm_sendtermreq()");
  288.  
  289.     if ( fsm_p->retry <= 0 )
  290.         return -1;
  291.  
  292.     fsm_p->retry--;
  293.     fsm_timer(fsm_p);
  294.     return( fsm_send(fsm_p, TERM_REQ, 0, NULLBUF) );
  295. }
  296.  
  297.  
  298. /************************************************************************/
  299. /* Send Terminate Ack */
  300. static int
  301. fsm_sendtermack(fsm_p,id)
  302. struct fsm_s *fsm_p;
  303. byte_t id;
  304. {
  305.     PPP_DEBUG_ROUTINES("fsm_sendtermack()");
  306.  
  307.     return( fsm_send(fsm_p, TERM_ACK, id, NULLBUF) );
  308. }
  309.  
  310.  
  311. /************************************************************************/
  312. /* Reset state machine */
  313. static void
  314. fsm_reset(fsm_p)
  315. struct fsm_s *fsm_p;
  316. {
  317.     PPP_DEBUG_ROUTINES("fsm_reset()");
  318.  
  319.     fsm_p->state = (fsm_p->flags & (FSM_ACTIVE | FSM_PASSIVE))
  320.             ? fsmLISTEN : fsmCLOSED;
  321.     fsm_p->retry = fsm_p->try_req;
  322.     fsm_p->retry_nak = fsm_p->try_nak;
  323.  
  324.     (*fsm_p->pdc->reset)(fsm_p);
  325. }
  326.  
  327.  
  328. /************************************************************************/
  329. /* Configuration negotiation complete */
  330. static void
  331. fsm_opening(fsm_p)
  332. struct fsm_s *fsm_p;
  333. {
  334.     fsm_log(fsm_p, "Open");
  335.  
  336.     stop_timer(&(fsm_p->timer));
  337.  
  338.     (*fsm_p->pdc->opening)(fsm_p);
  339.     fsm_p->state = fsmOPENED;
  340. }
  341.  
  342.  
  343. /************************************************************************/
  344. /*            E V E N T   P R O C E S S I N G            */
  345. /************************************************************************/
  346.  
  347. /* Process incoming packet */
  348. void
  349. fsm_proc(fsm_p,bp)
  350. struct fsm_s *fsm_p;
  351. struct mbuf *bp;
  352. {
  353.     struct config_hdr hdr;
  354.  
  355.     PPPtrace = fsm_p->ppp_p->trace;
  356.  
  357.     ntohcnf(&hdr, &bp);
  358.     if (PPPtrace > 1)
  359.         log(-1,    "%s PPP/%s %-8s;"
  360.             " Processing option: %s, id: %d, len: %d",
  361.             fsm_p->ppp_p->iface->name,
  362.             fsm_p->pdc->name,
  363.             fsmStates[fsm_p->state],
  364.             fsmCodes[hdr.code],
  365.             hdr.id,    hdr.len);
  366.  
  367.     hdr.len -= CONFIG_HDR_LEN;        /* Length includes envelope */
  368.     trim_mbuf(&bp, hdr.len);        /* Trim off padding */
  369.  
  370.     switch(hdr.code) {
  371.     case CONFIG_REQ:
  372.         switch(fsm_p->state) {
  373.         case fsmOPENED:        /* Unexpected event? */
  374.             (*fsm_p->pdc->closing)(fsm_p);
  375.             fsm_reset(fsm_p);
  376.             /* fallthru */
  377.         case fsmLISTEN:
  378.             fsm_sendreq(fsm_p);
  379.             /* fallthru */
  380.         case fsmREQ_Sent:
  381.         case fsmACK_Sent:    /* Unexpected event? */
  382.             fsm_p->state =
  383.             ((*fsm_p->pdc->request)(fsm_p, &hdr, bp) == 0)
  384.                 ? fsmACK_Sent : fsmREQ_Sent;
  385.             break;
  386.  
  387.         case fsmACK_Rcvd:
  388.             if ((*fsm_p->pdc->request)(fsm_p, &hdr, bp) == 0) {
  389.                 fsm_opening(fsm_p);
  390.             } else {
  391.                 /* give peer time to respond */
  392.                 fsm_timer(fsm_p);
  393.             }
  394.             break;
  395.  
  396.         case fsmCLOSED:
  397.             /* Don't accept any connections */
  398.             fsm_sendtermack(fsm_p, hdr.id);
  399.             /* fallthru */
  400.         case fsmTERM_Sent:
  401.             /* We are attempting to close connection; */
  402.             /* wait for timeout to resend a Terminate Request */
  403.             free_p(bp);
  404.             break;
  405.         };
  406.         break;
  407.  
  408.     case CONFIG_ACK:
  409.         switch(fsm_p->state) {
  410.         case fsmREQ_Sent:
  411.             if ((*fsm_p->pdc->ack)(fsm_p, &hdr, bp) == 0) {
  412.                 fsm_p->state = fsmACK_Rcvd;
  413.             }
  414.             break;
  415.  
  416.         case fsmACK_Sent:
  417.             if ((*fsm_p->pdc->ack)(fsm_p, &hdr, bp) == 0) {
  418.                 fsm_opening(fsm_p);
  419.             }
  420.             break;
  421.  
  422.         case fsmOPENED:        /* Unexpected event? */
  423.             (*fsm_p->pdc->closing)(fsm_p);
  424.             fsm_reset(fsm_p);
  425.             /* fallthru */
  426.         case fsmACK_Rcvd:    /* Unexpected event? */
  427.             free_p(bp);
  428.             fsm_sendreq(fsm_p);
  429.             fsm_p->state = fsmREQ_Sent;
  430.             break;
  431.  
  432.         case fsmCLOSED:
  433.         case fsmLISTEN:
  434.             /* Out of Sync; kill the remote */
  435.             fsm_sendtermack(fsm_p, hdr.id);
  436.             /* fallthru */
  437.         case fsmTERM_Sent:
  438.             /* We are attempting to close connection; */
  439.             /* wait for timeout to resend a Terminate Request */
  440.             free_p(bp);
  441.             break;
  442.         };
  443.         break;
  444.  
  445.     case CONFIG_NAK:
  446.         switch(fsm_p->state) {
  447.         case fsmREQ_Sent:
  448.         case fsmACK_Sent:
  449.             /* Update our config request to reflect NAKed options */
  450.             if ((*fsm_p->pdc->nak)(fsm_p, &hdr, bp) == 0) {
  451.                 /* Send updated config request */
  452.                 fsm_sendreq(fsm_p);
  453.             }
  454.             break;
  455.  
  456.         case fsmOPENED:        /* Unexpected event? */
  457.             (*fsm_p->pdc->closing)(fsm_p);
  458.             fsm_reset(fsm_p);
  459.             /* fallthru */
  460.         case fsmACK_Rcvd:    /* Unexpected event? */
  461.             free_p(bp);
  462.             fsm_sendreq(fsm_p);
  463.             fsm_p->state = fsmREQ_Sent;
  464.             break;
  465.  
  466.         case fsmCLOSED:
  467.         case fsmLISTEN:
  468.             /* Out of Sync; kill the remote */
  469.             fsm_sendtermack(fsm_p, hdr.id);
  470.             /* fallthru */
  471.         case fsmTERM_Sent:
  472.             /* We are attempting to close connection; */
  473.             /* wait for timeout to resend a Terminate Request */
  474.             free_p(bp);
  475.             break;
  476.         };
  477.         break;
  478.  
  479.     case CONFIG_REJ:
  480.         switch(fsm_p->state) {
  481.         case fsmREQ_Sent:
  482.         case fsmACK_Sent:
  483.             if((*fsm_p->pdc->reject)(fsm_p, &hdr, bp) == 0) {
  484.                 fsm_sendreq(fsm_p);
  485.             }
  486.             break;
  487.  
  488.         case fsmOPENED:        /* Unexpected event? */
  489.             (*fsm_p->pdc->closing)(fsm_p);
  490.             fsm_reset(fsm_p);
  491.             /* fallthru */
  492.         case fsmACK_Rcvd:    /* Unexpected event? */
  493.             free_p(bp);
  494.             fsm_sendreq(fsm_p);
  495.             fsm_p->state = fsmREQ_Sent;
  496.             break;
  497.  
  498.         case fsmCLOSED:
  499.         case fsmLISTEN:
  500.             /* Out of Sync; kill the remote */
  501.             fsm_sendtermack(fsm_p, hdr.id);
  502.             /* fallthru */
  503.         case fsmTERM_Sent:
  504.             /* We are attempting to close connection; */
  505.             /* wait for timeout to resend a Terminate Request */
  506.             free_p(bp);
  507.             break;
  508.         };
  509.         break;
  510.  
  511.     case TERM_REQ:
  512.         fsm_log(fsm_p, "Peer requested Termination");
  513.  
  514.         switch(fsm_p->state) {
  515.         case fsmOPENED:
  516.             (*fsm_p->pdc->closing)(fsm_p);
  517.             fsm_sendtermack(fsm_p, hdr.id);
  518.             fsm_reset(fsm_p);
  519.             break;
  520.  
  521.         case fsmACK_Rcvd:
  522.         case fsmACK_Sent:
  523.             fsm_p->state = fsmREQ_Sent;
  524.             /* fallthru */
  525.         case fsmREQ_Sent:
  526.         case fsmTERM_Sent:
  527.             /* waiting for timeout */
  528.             /* fallthru */
  529.         case fsmCLOSED:
  530.         case fsmLISTEN:
  531.             /* Unexpected, but make them happy */
  532.             fsm_sendtermack(fsm_p, hdr.id);
  533.             break;
  534.         };
  535.         break;
  536.  
  537.     case TERM_ACK:
  538.         switch(fsm_p->state) {
  539.         case fsmTERM_Sent:
  540.             stop_timer(&(fsm_p->timer));
  541.  
  542.             fsm_log(fsm_p, "Terminated");
  543.             fsm_reset(fsm_p);
  544.             (*fsm_p->pdc->stopping)(fsm_p);
  545.             break;
  546.  
  547.         case fsmOPENED:
  548.             /* Remote host has abruptly closed connection */
  549.             fsm_log(fsm_p, "Terminated unexpectly");
  550.             (*fsm_p->pdc->closing)(fsm_p);
  551.             fsm_reset(fsm_p);
  552.             if ( fsm_sendreq(fsm_p) == 0 ) {
  553.                 fsm_p->state = fsmREQ_Sent;
  554.             }
  555.             break;
  556.  
  557.         case fsmACK_Sent:
  558.         case fsmACK_Rcvd:
  559.             fsm_p->state = fsmREQ_Sent;
  560.             /* fallthru */
  561.         case fsmREQ_Sent:
  562.             /* waiting for timeout */
  563.             /* fallthru */
  564.         case fsmCLOSED:
  565.         case fsmLISTEN:
  566.             /* Unexpected, but no action needed */
  567.             break;
  568.         };
  569.         break;
  570.  
  571.     case CODE_REJ:
  572.         log(-1,"%s: PPP/%s Code Reject;"
  573.             " indicates faulty implementation",
  574.             fsm_p->ppp_p->iface->name,
  575.             fsm_p->pdc->name);
  576.         fsm_reset(fsm_p);
  577.         (*fsm_p->pdc->stopping)(fsm_p);
  578.         free_p(bp);
  579.         break;
  580.  
  581.     case PROT_REJ:
  582.         log(-1,"%s: PPP/%s Protocol Reject;"
  583.             " please do not use this protocol",
  584.             fsm_p->ppp_p->iface->name,
  585.             fsm_p->pdc->name);
  586.         free_p(bp);
  587.         break;
  588.  
  589.     case ECHO_REQ:
  590.         switch(fsm_p->state) {
  591.         case fsmOPENED:
  592.             fsm_send( fsm_p, ECHO_REPLY, hdr.id, bp );
  593.             break;
  594.  
  595.         case fsmCLOSED:
  596.         case fsmLISTEN:
  597.             /* Out of Sync; kill the remote */
  598.             fsm_sendtermack(fsm_p, hdr.id);
  599.             /* fallthru */
  600.         case fsmREQ_Sent:
  601.         case fsmACK_Rcvd:
  602.         case fsmACK_Sent:
  603.         case fsmTERM_Sent:
  604.             /* ignore */
  605.             free_p(bp);
  606.             break;
  607.         };
  608.         break;
  609.  
  610.     case ECHO_REPLY:
  611.     case DISCARD_REQ:
  612.     case QUALITY_REPORT:
  613.         free_p(bp);
  614.         break;
  615.  
  616.     default:
  617.         log(-1,"%s: PPP/%s Unknown packet type: %d;"
  618.             " sending Code Reject",
  619.             fsm_p->ppp_p->iface->name,
  620.             fsm_p->pdc->name,
  621.             hdr.code);
  622.  
  623.         hdr.len += CONFIG_HDR_LEN;    /* restore length */
  624.         bp = htoncnf( &hdr, bp );    /* put header back on */
  625.         fsm_send( fsm_p, CODE_REJ, hdr.id, bp );
  626.  
  627.         switch(fsm_p->state) {
  628.         case fsmREQ_Sent:
  629.         case fsmACK_Rcvd:
  630.         case fsmACK_Sent:
  631.         case fsmOPENED:
  632.             fsm_p->state = fsmLISTEN;
  633.             break;
  634.  
  635.         case fsmCLOSED:
  636.         case fsmLISTEN:
  637.         case fsmTERM_Sent:
  638.             /* no change */
  639.             break;
  640.         };
  641.         break;
  642.     }
  643. }
  644.  
  645.  
  646. /************************************************************************/
  647. /* Timeout while waiting for reply from remote host */
  648. static void
  649. fsm_timeout(vp)
  650. void *vp;
  651. {
  652.     struct fsm_s *fsm_p = (struct fsm_s *)vp;
  653.  
  654.     PPPtrace = fsm_p->ppp_p->trace;
  655.  
  656.     fsm_log( fsm_p, "Timeout" );
  657.  
  658.     switch(fsm_p->state) {
  659.     case fsmREQ_Sent:
  660.     case fsmACK_Rcvd:
  661.     case fsmACK_Sent:
  662.         if (fsm_p->retry > 0) {
  663.             fsm_sendreq(fsm_p);
  664.             fsm_p->state = fsmREQ_Sent;
  665.         } else {
  666.             fsm_log(fsm_p, "Request retry exceeded");
  667.             fsm_reset(fsm_p);
  668.             (*fsm_p->pdc->stopping)(fsm_p);
  669.         }
  670.         break;
  671.  
  672.     case fsmTERM_Sent:
  673.         if (fsm_p->retry > 0) {
  674.             fsm_sendtermreq(fsm_p);
  675.         } else {
  676.             fsm_log(fsm_p, "Terminate retry exceeded");
  677.             fsm_reset(fsm_p);
  678.             (*fsm_p->pdc->stopping)(fsm_p);
  679.         }
  680.         break;
  681.  
  682.     case fsmCLOSED:
  683.     case fsmLISTEN:
  684.     case fsmOPENED:
  685.         /* nothing to do */
  686.         break;
  687.     }
  688. }
  689.  
  690.  
  691. /************************************************************************/
  692. /*            I N I T I A L I Z A T I O N            */
  693. /************************************************************************/
  694.  
  695. /* Start FSM (after open event, and physical line up) */
  696. void
  697. fsm_start(fsm_p)
  698. struct fsm_s *fsm_p;
  699. {
  700.     if ( fsm_p->pdv == NULL )
  701.         return;
  702.  
  703.     PPPtrace = fsm_p->ppp_p->trace;
  704.  
  705.     fsm_log(fsm_p, "Start");
  706.  
  707.     if ( !(fsm_p->flags & (FSM_ACTIVE | FSM_PASSIVE)) )
  708.         return;
  709.  
  710.     switch ( fsm_p->state ) {
  711.     case fsmCLOSED:
  712.     case fsmLISTEN:
  713.     case fsmTERM_Sent:
  714.         fsm_reset(fsm_p);
  715.         (*fsm_p->pdc->starting)(fsm_p);
  716.  
  717.         if ( fsm_p->flags & FSM_ACTIVE ){
  718.             fsm_sendreq(fsm_p);
  719.             fsm_p->state = fsmREQ_Sent;
  720.         }
  721.         break;
  722.     default:
  723.         /* already started */
  724.         break;
  725.     };
  726. }
  727.  
  728.  
  729. /************************************************************************/
  730. /* Physical Line Down Event */
  731. void
  732. fsm_down(fsm_p)
  733. struct fsm_s *fsm_p;
  734. {
  735.     if ( fsm_p->pdv == NULL )
  736.         return;
  737.  
  738.     PPPtrace = fsm_p->ppp_p->trace;
  739.  
  740.     fsm_log(fsm_p, "Down");
  741.  
  742.     switch ( fsm_p->state ) {
  743.     case fsmREQ_Sent:
  744.     case fsmACK_Rcvd:
  745.     case fsmACK_Sent:
  746.         stop_timer(&(fsm_p->timer));
  747.         fsm_reset(fsm_p);
  748.         (*fsm_p->pdc->stopping)(fsm_p);
  749.         break;
  750.  
  751.     case fsmOPENED:
  752.         (*fsm_p->pdc->closing)(fsm_p);
  753.         /* fallthru */
  754.     case fsmTERM_Sent:
  755.         fsm_reset(fsm_p);
  756.         (*fsm_p->pdc->stopping)(fsm_p);
  757.         break;
  758.  
  759.     case fsmCLOSED:
  760.     case fsmLISTEN:
  761.         /* nothing to do */
  762.         break;
  763.     };
  764. }
  765.  
  766.  
  767. /************************************************************************/
  768. /* Close the connection */
  769. void
  770. fsm_close(fsm_p)
  771. struct fsm_s *fsm_p;
  772. {
  773.     if ( fsm_p->pdv == NULL )
  774.         return;
  775.  
  776.     PPPtrace = fsm_p->ppp_p->trace;
  777.  
  778.     fsm_log(fsm_p, "Close");
  779.  
  780.     switch ( fsm_p->state ) {
  781.     case fsmOPENED:
  782.         (*fsm_p->pdc->closing)(fsm_p);
  783.         /* fallthru */
  784.     case fsmACK_Sent:
  785.         fsm_p->retry = fsm_p->try_terminate;
  786.         fsm_sendtermreq(fsm_p);
  787.         fsm_p->state = fsmTERM_Sent;
  788.         break;
  789.  
  790.     case fsmREQ_Sent:
  791.     case fsmACK_Rcvd:
  792.         /* simply wait for REQ timeout to expire */
  793.         fsm_p->retry = 0;
  794.         fsm_p->state = fsmTERM_Sent;
  795.         break;
  796.  
  797.     case fsmLISTEN:
  798.         fsm_p->state = fsmCLOSED;
  799.         break;
  800.  
  801.     case fsmTERM_Sent:
  802.     case fsmCLOSED:
  803.         /* nothing to do */
  804.         break;
  805.     };
  806. }
  807.  
  808.  
  809. /************************************************************************/
  810. /* Initialize the fsm for this protocol
  811.  * Called from protocol _init
  812.  */
  813. void
  814. fsm_init(fsm_p)
  815. struct fsm_s *fsm_p;
  816. {
  817.     struct timer *t = &(fsm_p->timer);
  818.  
  819.     PPP_DEBUG_ROUTINES("fsm_init()");
  820.  
  821.     fsm_p->try_req = fsm_p->pdc->try_req;
  822.     fsm_p->try_nak = fsm_p->pdc->try_nak;
  823.     fsm_p->try_terminate = fsm_p->pdc->try_terminate;
  824.     fsm_reset(fsm_p);
  825.  
  826.     /* Initialize timer */
  827.     t->func = (void (*)())fsm_timeout;
  828.     t->arg = (void *)fsm_p;
  829.     set_timer(t, fsm_p->pdc->timeout);
  830.     fsm_timer(fsm_p);
  831.     stop_timer(t);
  832. }
  833.  
  834.  
  835. void
  836. fsm_free(fsm_p)
  837. struct fsm_s *fsm_p;
  838. {
  839.     if ( fsm_p->pdv != NULL ) {
  840.         (*fsm_p->pdc->free)(fsm_p);
  841.  
  842.         free( fsm_p->pdv );
  843.         fsm_p->pdv = NULL;
  844.     }
  845. }
  846.  
  847.  
  848.